/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.nageoffer.shortlink.project.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nageoffer.shortlink.project.dao.entity.ShortLinkDO;
import com.nageoffer.shortlink.project.dao.mapper.ShortLinkMapper;
import com.nageoffer.shortlink.project.dto.req.RecycleBinRecoverReqDTO;
import com.nageoffer.shortlink.project.dto.req.RecycleBinRemoveReqDTO;
import com.nageoffer.shortlink.project.dto.req.RecycleBinSaveReqDTO;
import com.nageoffer.shortlink.project.dto.req.ShortLinkRecycleBinPageReqDTO;
import com.nageoffer.shortlink.project.dto.resp.ShortLinkPageRespDTO;
import com.nageoffer.shortlink.project.service.RecycleBinService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import static com.nageoffer.shortlink.project.common.constant.RedisKeyConstant.GOTO_IS_NULL_SHORT_LINK_KEY;
import static com.nageoffer.shortlink.project.common.constant.RedisKeyConstant.GOTO_SHORT_LINK_KEY;

/**
 * 回收站管理接口实现层
 */
@Service
@RequiredArgsConstructor
public class RecycleBinServiceImpl extends ServiceImpl<ShortLinkMapper, ShortLinkDO> implements RecycleBinService {

    private final StringRedisTemplate stringRedisTemplate;

    /**
     * 将指定的短链接信息保存到回收站
     * 此方法通过更新数据库中对应短链接的启用状态来实现将其移入回收站的功能
     *
     * @param requestParam 包含短链接相关信息的请求参数对象，用于定位数据库中的特定短链接
     */
    @Override
    public void saveRecycleBin(RecycleBinSaveReqDTO requestParam) {
        // 创建更新条件构造器，用于精确匹配待更新的短链接记录
        LambdaUpdateWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDO.class)
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getEnableStatus, 0)
                .eq(ShortLinkDO::getDelFlag, 0);

        // 创建ShortLinkDO对象，仅设置需更新的字段：启用状态为1，表示已禁用
        ShortLinkDO shortLinkDO = ShortLinkDO.builder()
                .enableStatus(1)
                .build();

        // 执行更新操作，根据updateWrapper中的条件更新短链接记录
        baseMapper.update(shortLinkDO, updateWrapper);

        // 删除Redis中对应的短链接缓存，以保持数据一致性
        stringRedisTemplate.delete(String.format(GOTO_SHORT_LINK_KEY, requestParam.getFullShortUrl()));
    }

    /**
     * 分页查询短链回收站信息
     * 
     * @param requestParam 短链回收站分页查询请求参数
     * @return 短链回收站分页查询结果
     */
    @Override
    public IPage<ShortLinkPageRespDTO> pageShortLink(ShortLinkRecycleBinPageReqDTO requestParam) {
        // 调用Mapper方法，获取短链回收站数据分页结果
        IPage<ShortLinkDO> resultPage = baseMapper.pageRecycleBinLink(requestParam);
        
        // 将查询结果转换为ShortLinkPageRespDTO对象，并对域名进行格式化
        return resultPage.convert(each -> {
            // 将ShortLinkDO对象转换为ShortLinkPageRespDTO对象
            ShortLinkPageRespDTO result = BeanUtil.toBean(each, ShortLinkPageRespDTO.class);
            
            // 为域名添加http协议前缀
            result.setDomain("http://" + result.getDomain());
            
            // 返回转换后的对象
            return result;
        });
    }

    /**
     * 恢复回收站中的短链接
     * 此方法用于将回收站中的短链接恢复到可用状态
     * 它通过更新短链接的启用状态来实现这一点
     * 
     * @param requestParam 包含恢复请求的参数，包括完整的短链接URL、全局ID等
     */
    @Override
    public void recoverRecycleBin(RecycleBinRecoverReqDTO requestParam) {
        // 创建一个Lambda更新包装器，用于构建更新条件
        LambdaUpdateWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDO.class)
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getEnableStatus, 1)
                .eq(ShortLinkDO::getDelFlag, 0);
        
        // 创建一个ShortLinkDO对象，仅设置启用状态为0，表示恢复后的链接将被禁用
        ShortLinkDO shortLinkDO = ShortLinkDO.builder()
                .enableStatus(0)
                .build();
        
        // 执行更新操作，根据条件更新短链接的启用状态
        baseMapper.update(shortLinkDO, updateWrapper);
        
        // 删除Redis中与该短链接相关的缓存键
        stringRedisTemplate.delete(String.format(GOTO_IS_NULL_SHORT_LINK_KEY, requestParam.getFullShortUrl()));
    }

    /**
     * 移除回收站中的短链接
     * 
     * @param requestParam 包含全量短网址和组ID的请求参数对象
     */
    @Override
    public void removeRecycleBin(RecycleBinRemoveReqDTO requestParam) {
        // 构建更新条件
        LambdaUpdateWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDO.class)
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getEnableStatus, 1)
                .eq(ShortLinkDO::getDelTime, 0L)
                .eq(ShortLinkDO::getDelFlag, 0);
        
        // 创建用于更新的ShortLinkDO对象，仅设置删除时间
        ShortLinkDO delShortLinkDO = ShortLinkDO.builder()
                .delTime(System.currentTimeMillis())
                .build();
        
        // 设置删除标志为1，表示已删除
        delShortLinkDO.setDelFlag(1);
        
        // 执行更新操作，将符合条件的短链接标记为已删除
        baseMapper.update(delShortLinkDO, updateWrapper);
    }
}
